int Element_FromBytes(Element & e, int type, unsigned char *data) { string d = ""; if(is_base64((unsigned char) data[0])) { string b64_encoded((char *) data); d = _base64_decode(b64_encoded); } else { return ELEMENT_INVALID_ARG; } if(type == ZR_t) { bn_read_bin(e.zr.z, (unsigned char *) d.c_str(), d.size()); } else if(type == G1_t) { return g1_read_bin(e.g1.g, (unsigned char *) d.c_str(), d.size()); // x & y } else if(type == G2_t) { return g2_read_bin(e.g2.g, (unsigned char *) d.c_str(), d.size()); // x1, y1 & x2, y2 } else if(type == GT_t) { return gt_read_bin(e.gt.g, (unsigned char *) d.c_str(), d.size()); // x1-6 && y1-6 } return ELEMENT_INVALID_ARG; }
/** * \brief Decode Base64 encoded string to binary data * * Decode Base64 encoded string \p in to binary data \p out * * \param in Reference to a Base64 encoded string * \param in_sz length of \p in in bytes (excluding the terminating \c NUL) * \param out Pre-allocated buffer of size approx as \p in_sz * \param out_sz Value-result argument initially containing the total * size of \p out in bytes. On successful return it * holds the decoded buffer size. * * \retval 0 on success * \retval ~0 on failure */ int u_b64_decode (const char *in, size_t in_sz, uint8_t *out, size_t *out_sz) { char buf[4]; size_t i, len, pad, tot_sz = *out_sz; uint8_t *pout; dbg_return_if (in == NULL, ~0); dbg_return_if (in_sz == 0, ~0); dbg_return_if (out == NULL, ~0); dbg_return_if (out_sz == NULL, ~0); for (pout = out; in_sz; ) { for (pad = 0, len = 0, i = 0; i < 4; ++i) { if (in_sz && in_sz-- > 0) /* Avoid wrapping around in_sz. */ { buf[i] = *in++; if (buf[i] == '=') ++pad; else if (!is_base64(buf[i])) return ~0; ++len; } else buf[i] = '\0'; } if (len) { size_t nlen = 3 - pad; if (tot_sz >= nlen) { chunk_decode(buf, pout); tot_sz -= nlen; /* Take care of subtracting pad bytes. */ pout += nlen; } else return ~0; /* Not enough space. */ } } *out_sz -= tot_sz; return 0; }
/* See if we need to add the "Salted__" string to the front of the * encrypted data. */ int add_salted_str(fko_ctx_t ctx) { char *tbuf; #if AFL_FUZZING ctx->added_salted_str = 1; return(FKO_SUCCESS); #endif /* We only add the base64 encoded salt to data that is already base64 * encoded */ if(is_base64((unsigned char *)ctx->encrypted_msg, ctx->encrypted_msg_len) == 0) return(FKO_ERROR_INVALID_DATA_ENCODE_NOTBASE64); if(constant_runtime_cmp(ctx->encrypted_msg, B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN) != 0) { /* We need to realloc space for the salt. */ tbuf = realloc(ctx->encrypted_msg, ctx->encrypted_msg_len + B64_RIJNDAEL_SALT_STR_LEN+1); if(tbuf == NULL) return(FKO_ERROR_MEMORY_ALLOCATION); memmove(tbuf+B64_RIJNDAEL_SALT_STR_LEN, tbuf, ctx->encrypted_msg_len); //Ìí¼ÓÑΡ£ ctx->encrypted_msg = memcpy(tbuf, B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN); /* Adjust the encoded msg len for added SALT value and Make sure we * are still a properly NULL-terminated string (Ubuntu was one system * for which this was an issue). */ ctx->encrypted_msg_len += B64_RIJNDAEL_SALT_STR_LEN; tbuf[ctx->encrypted_msg_len] = '\0'; ctx->added_salted_str = 1; } return(FKO_SUCCESS); }
/** * Count the number of valid base64 characters in the supplied input * buffer. * @desc this function counts the number of valid base64 characters, * skipping CR and LF characters. Invalid characters are treated as * end of buffer markers. * * \param inbuff the buffer to check. * \param inputlen the length of the input buffer. * \return the number of valid base64 characters. */ static uint32_t get_num_valid_characters( const uint8_t* inbuff, size_t inputlen ) { uint32_t validCharCount=0; uint32_t idx=0; while ( idx < inputlen ) { if ( is_base64( inbuff[idx] ) ) { ++validCharCount; ++idx; } else if ( inbuff[idx] == '\r' || inbuff[idx] == '\n' ) { ++idx; } else { break; } } return validCharCount; }
/* Validate and in some cases preprocess/reformat the SPA data. Return an * error code value if there is any indication the data is not valid spa data. */ static int preprocess_spa_data(const fko_srv_options_t *opts, spa_pkt_info_t *spa_pkt) { char *ndx = (char *)&(spa_pkt->packet_data); int i, pkt_data_len = 0; pkt_data_len = spa_pkt->packet_data_len; /* At this point, we can reset the packet data length to 0. This is our * indicator to the rest of the program that we do not have a current * spa packet to process (after this one that is). */ spa_pkt->packet_data_len = 0; /* These two checks are already done in process_packet(), but this is a * defensive measure to run them again here */ if(pkt_data_len < MIN_SPA_DATA_SIZE) return(SPA_MSG_BAD_DATA); if(pkt_data_len > MAX_SPA_PACKET_LEN) return(SPA_MSG_BAD_DATA); /* Ignore any SPA packets that contain the Rijndael or GnuPG prefixes * since an attacker might have tacked them on to a previously seen * SPA packet in an attempt to get past the replay check. And, we're * no worse off since a legitimate SPA packet that happens to include * a prefix after the outer one is stripped off won't decrypt properly * anyway because libfko would not add a new one. */ if(constant_runtime_cmp(ndx, B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN) == 0) return(SPA_MSG_BAD_DATA); if(pkt_data_len > MIN_GNUPG_MSG_SIZE && constant_runtime_cmp(ndx, B64_GPG_PREFIX, B64_GPG_PREFIX_STR_LEN) == 0) return(SPA_MSG_BAD_DATA); /* Detect and parse out SPA data from an HTTP request. If the SPA data * starts with "GET /" and the user agent starts with "Fwknop", then * assume it is a SPA over HTTP request. */ if(strncasecmp(opts->config[CONF_ENABLE_SPA_OVER_HTTP], "Y", 1) == 0 && strncasecmp(ndx, "GET /", 5) == 0 && strstr(ndx, "User-Agent: Fwknop") != NULL) { /* This looks like an HTTP request, so let's see if we are * configured to accept such request and if so, find the SPA * data. */ /* Now extract, adjust (convert characters translated by the fwknop * client), and reset the SPA message itself. */ strlcpy((char *)spa_pkt->packet_data, ndx+5, pkt_data_len); pkt_data_len -= 5; for(i=0; i<pkt_data_len; i++) { if(isspace(*ndx)) /* The first space marks the end of the req */ { *ndx = '\0'; break; } else if(*ndx == '-') /* Convert '-' to '+' */ *ndx = '+'; else if(*ndx == '_') /* Convert '_' to '/' */ *ndx = '/'; ndx++; } if(i < MIN_SPA_DATA_SIZE) return(SPA_MSG_BAD_DATA); spa_pkt->packet_data_len = pkt_data_len = i; } /* Require base64-encoded data */ if(! is_base64(spa_pkt->packet_data, pkt_data_len)) return(SPA_MSG_NOT_SPA_DATA); /* If we made it here, we have no reason to assume this is not SPA data. * The ultimate test will be whether the SPA data authenticates via an * HMAC anyway. */ return(FKO_SUCCESS); }
int Element_FromBytes(Element &e, int type, unsigned char *data) { if(type == ZR_t) { if(is_base64((unsigned char) data[0])) { string b64_encoded((char *) data); string s = _base64_decode(b64_encoded); int cnt = 0; Big b = Big(bytesToBig(s, &cnt)); e = Element(b); // cout << "Element_FromBytes: " << e << endl; return TRUE; } } else if(type == G1_t) { if(is_base64((unsigned char) data[0])) { string b64_encoded((char *) data); string s = _base64_decode(b64_encoded); int cnt = 0; Big x, y; x = bytesToBig(s, &cnt); s = s.substr(cnt); y = bytesToBig(s, &cnt); // cout << "point => (" << x << ", " << y << ")" << endl; G1 p; p.g.set(x, y); e = Element(p); //cout << "Element_FromBytes: " << e << endl; return TRUE; } } #if ASYMMETRIC == 1 else if(type == G2_t) { if(is_base64((unsigned char) data[0])) { string b64_encoded((char *) data); string s = _base64_decode(b64_encoded); // cout << "original => " << s << endl; int cnt = 0; G2 p; #if BUILD_MNT_CURVE == 1 ZZn a[MNT_G2_SIZE]; for(int i = 0; i < MNT_G2_SIZE; i++) { Big b = bytesToBig(s, &cnt); a[i] = ZZn( b ); // retrieve all six coordinates s = s.substr(cnt); } ZZn3 x (a[0], a[1], a[2]); ZZn3 y (a[3], a[4], a[5]); p.g.set(x, y); #elif BUILD_BN_CURVE == 1 Big a[BN_G2_SIZE]; for(int i = 0; i < BN_G2_SIZE; i++) { a[i] = bytesToBig(s, &cnt); s = s.substr(cnt); // advance s ptr } ZZn2 x1(a[0], a[1]); // each zzn2 has a (x, y) coordinate of type Big ZZn2 y1(a[2], a[3]); p.g.set(x1, y1); #endif e = Element(p); //cout << "Element_FromBytes: " << e << endl; return TRUE; } } #endif else if(type == GT_t) { if(is_base64((unsigned char) data[0])) { string b64_encoded((char *) data); string s = _base64_decode(b64_encoded); // cout << "original => " << s << endl; int cnt = 0; GT p; #if BUILD_MNT_CURVE == 1 Big a[MNT_GT_SIZE]; for(int i = 0; i < MNT_GT_SIZE; i++) { a[i] = bytesToBig(s, &cnt); s = s.substr(cnt); // advance s ptr } ZZn2 x, y, z; x.set(a[0], a[1]); y.set(a[2], a[3]); z.set(a[4], a[5]); p.g.set(x, y, z); #elif BUILD_BN_CURVE == 1 Big a[BN_GT_SIZE]; for(int i = 0; i < BN_GT_SIZE; i++) { a[i] = bytesToBig(s, &cnt); s = s.substr(cnt); // advance s ptr } ZZn2 x0, x1, y0, y1, z0, z1; x0.set(a[0], a[1]); x1.set(a[2], a[3]); y0.set(a[4], a[5]); y1.set(a[6], a[7]); z0.set(a[8], a[9]); z1.set(a[10], a[11]); ZZn4 x(x0, x1); ZZn4 y(y0, y1); ZZn4 z(z0, z1); p.g.set(x, y, z); #elif BUILD_SS_CURVE == 1 // must be symmetric Big a[SS_GT_SIZE]; for(int i = 0; i < SS_GT_SIZE; i++) { a[i] = bytesToBig(s, &cnt); s = s.substr(cnt); // advance s ptr } p.g.set(a[0], a[1]); #endif e = Element(p); //cout << "Element_FromBytes: " << e << endl; return TRUE; } } return 0; }