Exemplo n.º 1
0
static int aria_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                              const unsigned char *in, size_t len)
{
    EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx);
    int rv = -1;

    /* Encrypt/decrypt must be performed in place */
    if (out != in
        || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
        return -1;
    /*
     * Set IV from start of buffer or generate IV and write to start of
     * buffer.
     */
    if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CIPHER_CTX_encrypting(ctx) ?
                            EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV,
                            EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
        goto err;
    /* Use saved AAD */
    if (CRYPTO_gcm128_aad(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx),
                          gctx->tls_aad_len))
        goto err;
    /* Fix buffer and length to point to payload */
    in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
    out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
    len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
    if (EVP_CIPHER_CTX_encrypting(ctx)) {
        /* Encrypt payload */
        if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
            goto err;
        out += len;
        /* Finally write tag */
        CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
        rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
    } else {
        /* Decrypt */
        if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
            goto err;
        /* Retrieve tag */
        CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx),
                          EVP_GCM_TLS_TAG_LEN);
        /* If tag mismatch wipe buffer */
        if (CRYPTO_memcmp(EVP_CIPHER_CTX_buf_noconst(ctx), in + len,
                          EVP_GCM_TLS_TAG_LEN)) {
            OPENSSL_cleanse(out, len);
            goto err;
        }
        rv = len;
    }

 err:
    gctx->iv_set = 0;
    gctx->tls_aad_len = -1;
    return rv;
}
Exemplo n.º 2
0
static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
                          size_t len) {
  EVP_AES_GCM_CTX *gctx = ctx->cipher_data;

  // If not set up, return error
  if (!gctx->key_set) {
    return -1;
  }
  if (!gctx->iv_set) {
    return -1;
  }

  if (in) {
    if (out == NULL) {
      if (!CRYPTO_gcm128_aad(&gctx->gcm, in, len)) {
        return -1;
      }
    } else if (ctx->encrypt) {
      if (gctx->ctr) {
        if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
                                         gctx->ctr)) {
          return -1;
        }
      } else {
        if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
          return -1;
        }
      }
    } else {
      if (gctx->ctr) {
        if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
                                         gctx->ctr)) {
          return -1;
        }
      } else {
        if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
          return -1;
        }
      }
    }
    return len;
  } else {
    if (!ctx->encrypt) {
      if (gctx->taglen < 0 ||
          !CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen)) {
        return -1;
      }
      gctx->iv_set = 0;
      return 0;
    }
    CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
    gctx->taglen = 16;
    // Don't reuse the IV
    gctx->iv_set = 0;
    return 0;
  }
}
Exemplo n.º 3
0
static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                          const unsigned char *in, size_t len)
{
    EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
    /* If not set up, return error */
    if (!gctx->key_set)
        return -1;

    if (gctx->tls_aad_len >= 0)
        return aes_gcm_tls_cipher(ctx, out, in, len);

    if (!gctx->iv_set)
        return -1;
    if (in) {
        if (out == NULL) {
            if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
                return -1;
        } else if (ctx->encrypt) {
            if (gctx->ctr) {
                if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
                                                in, out, len, gctx->ctr))
                    return -1;
            } else {
                if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
                    return -1;
            }
        } else {
            if (gctx->ctr) {
                if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
                                                in, out, len, gctx->ctr))
                    return -1;
            } else {
                if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
                    return -1;
            }
        }
        return len;
    } else {
        if (!ctx->encrypt) {
            if (gctx->taglen < 0)
                return -1;
            if (CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen) != 0)
                return -1;
            gctx->iv_set = 0;
            return 0;
        }
        CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
        gctx->taglen = 16;
        /* Don't reuse the IV */
        gctx->iv_set = 0;
        return 0;
    }

}
static int aead_aes_gcm_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
                             size_t *out_len, size_t max_out_len,
                             const uint8_t *nonce, size_t nonce_len,
                             const uint8_t *in, size_t in_len,
                             const uint8_t *ad, size_t ad_len) {
  size_t bulk = 0;
  const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
  uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN];
  size_t plaintext_len;
  GCM128_CONTEXT gcm;

  if (in_len < gcm_ctx->tag_len) {
    OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_open, CIPHER_R_BAD_DECRYPT);
    return 0;
  }

  plaintext_len = in_len - gcm_ctx->tag_len;

  if (max_out_len < plaintext_len) {
    OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_open, CIPHER_R_BUFFER_TOO_SMALL);
    return 0;
  }

  memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
  CRYPTO_gcm128_setiv(&gcm, nonce, nonce_len);

  if (!CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
    return 0;
  }

  if (gcm_ctx->ctr) {
    if (!CRYPTO_gcm128_decrypt_ctr32(&gcm, in + bulk, out + bulk,
                                     in_len - bulk - gcm_ctx->tag_len,
                                     gcm_ctx->ctr)) {
      return 0;
    }
  } else {
    if (!CRYPTO_gcm128_decrypt(&gcm, in + bulk, out + bulk,
                               in_len - bulk - gcm_ctx->tag_len)) {
      return 0;
    }
  }

  CRYPTO_gcm128_tag(&gcm, tag, gcm_ctx->tag_len);
  if (CRYPTO_memcmp(tag, in + plaintext_len, gcm_ctx->tag_len) != 0) {
    OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_open, CIPHER_R_BAD_DECRYPT);
    return 0;
  }

  *out_len = plaintext_len;
  return 1;
}
Exemplo n.º 5
0
int evp_aead_aes_gcm_open(const void *ctx_buf, uint8_t *out, size_t *out_len,
                          size_t max_out_len, const uint8_t *nonce,
                          const uint8_t *in, size_t in_len, const uint8_t *ad,
                          size_t ad_len) {
  aead_assert_open_seal_preconditions(alignof(struct aead_aes_gcm_ctx), ctx_buf,
                                      out, out_len, nonce, in, in_len, ad,
                                      ad_len);

  const struct aead_aes_gcm_ctx *gcm_ctx = ctx_buf;

  if (!aead_open_out_max_out_in_tag_len(out_len, max_out_len, in_len,
                                        EVP_AEAD_AES_GCM_TAG_LEN)) {
    /* |aead_open_out_max_out_in_tag_len| already called |OPENSSL_PUT_ERROR|. */
    return 0;
  }

  uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN];
  size_t plaintext_len;
  GCM128_CONTEXT gcm;

  plaintext_len = in_len - EVP_AEAD_AES_GCM_TAG_LEN;

  const AES_KEY *key = &gcm_ctx->ks.ks;

  memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
  CRYPTO_gcm128_set_96_bit_iv(&gcm, key, nonce);

  if (!CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
    return 0;
  }

  if (gcm_ctx->ctr) {
    if (!CRYPTO_gcm128_decrypt_ctr32(&gcm, key, in, out,
                                     in_len - EVP_AEAD_AES_GCM_TAG_LEN,
                                     gcm_ctx->ctr)) {
      return 0;
    }
  } else {
    if (!CRYPTO_gcm128_decrypt(&gcm, key, in, out,
                               in_len - EVP_AEAD_AES_GCM_TAG_LEN)) {
      return 0;
    }
  }

  CRYPTO_gcm128_tag(&gcm, tag, EVP_AEAD_AES_GCM_TAG_LEN);
  if (CRYPTO_memcmp(tag, in + plaintext_len, EVP_AEAD_AES_GCM_TAG_LEN) != 0) {
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
    return 0;
  }

  return 1;
}
Exemplo n.º 6
0
static int
aead_aes_gcm_open(const EVP_AEAD_CTX *ctx, unsigned char *out, size_t *out_len,
    size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
    const unsigned char *in, size_t in_len, const unsigned char *ad,
    size_t ad_len)
{
	const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
	unsigned char tag[EVP_AEAD_AES_GCM_TAG_LEN];
	GCM128_CONTEXT gcm;
	size_t plaintext_len;
	size_t bulk = 0;

	if (in_len < gcm_ctx->tag_len) {
		EVPerr(EVP_F_AEAD_AES_GCM_OPEN, EVP_R_BAD_DECRYPT);
		return 0;
	}

	plaintext_len = in_len - gcm_ctx->tag_len;

	if (max_out_len < plaintext_len) {
		EVPerr(EVP_F_AEAD_AES_GCM_OPEN, EVP_R_BUFFER_TOO_SMALL);
		return 0;
	}

	memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
	CRYPTO_gcm128_setiv(&gcm, nonce, nonce_len);

	if (CRYPTO_gcm128_aad(&gcm, ad, ad_len))
		return 0;

	if (gcm_ctx->ctr) {
		if (CRYPTO_gcm128_decrypt_ctr32(&gcm, in + bulk, out + bulk,
		    in_len - bulk - gcm_ctx->tag_len, gcm_ctx->ctr))
			return 0;
	} else {
		if (CRYPTO_gcm128_decrypt(&gcm, in + bulk, out + bulk,
		    in_len - bulk - gcm_ctx->tag_len))
			return 0;
	}

	CRYPTO_gcm128_tag(&gcm, tag, gcm_ctx->tag_len);
	if (CRYPTO_memcmp(tag, in + plaintext_len, gcm_ctx->tag_len) != 0) {
		EVPerr(EVP_F_AEAD_AES_GCM_OPEN, EVP_R_BAD_DECRYPT);
		return 0;
	}

	*out_len = plaintext_len;

	return 1;
}
Exemplo n.º 7
0
static int aead_aes_gcm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
                                    const uint8_t *nonce, size_t nonce_len,
                                    const uint8_t *in, size_t in_len,
                                    const uint8_t *in_tag, size_t in_tag_len,
                                    const uint8_t *ad, size_t ad_len) {
  const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
  uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN];

  if (nonce_len == 0) {
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
    return 0;
  }

  if (in_tag_len != ctx->tag_len) {
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
    return 0;
  }

  const AES_KEY *key = &gcm_ctx->ks.ks;

  GCM128_CONTEXT gcm;
  OPENSSL_memset(&gcm, 0, sizeof(gcm));
  OPENSSL_memcpy(&gcm.gcm_key, &gcm_ctx->gcm_key, sizeof(gcm.gcm_key));
  CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len);

  if (!CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
    return 0;
  }

  if (gcm_ctx->ctr) {
    if (!CRYPTO_gcm128_decrypt_ctr32(&gcm, key, in, out, in_len,
                                     gcm_ctx->ctr)) {
      return 0;
    }
  } else {
    if (!CRYPTO_gcm128_decrypt(&gcm, key, in, out, in_len)) {
      return 0;
    }
  }

  CRYPTO_gcm128_tag(&gcm, tag, ctx->tag_len);
  if (CRYPTO_memcmp(tag, in_tag, ctx->tag_len) != 0) {
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
    return 0;
  }

  return 1;
}
Exemplo n.º 8
0
static int aria_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                          const unsigned char *in, size_t len)
{
    EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx);

    /* If not set up, return error */
    if (!gctx->key_set)
        return -1;

    if (gctx->tls_aad_len >= 0)
        return aria_gcm_tls_cipher(ctx, out, in, len);

    if (!gctx->iv_set)
        return -1;
    if (in) {
        if (out == NULL) {
            if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
                return -1;
        } else if (EVP_CIPHER_CTX_encrypting(ctx)) {
            if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
                return -1;
        } else {
            if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
                return -1;
        }
        return len;
    }
    if (!EVP_CIPHER_CTX_encrypting(ctx)) {
        if (gctx->taglen < 0)
            return -1;
        if (CRYPTO_gcm128_finish(&gctx->gcm,
                                 EVP_CIPHER_CTX_buf_noconst(ctx),
                                 gctx->taglen) != 0)
            return -1;
        gctx->iv_set = 0;
        return 0;
    }
    CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), 16);
    gctx->taglen = 16;
    /* Don't reuse the IV */
    gctx->iv_set = 0;
    return 0;
}
static int aead_aes_gcm_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
                             size_t *out_len, size_t max_out_len,
                             const uint8_t *nonce, size_t nonce_len,
                             const uint8_t *in, size_t in_len,
                             const uint8_t *ad, size_t ad_len) {
  size_t bulk = 0;
  const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
  GCM128_CONTEXT gcm;

  if (in_len + gcm_ctx->tag_len < in_len) {
    OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_seal, CIPHER_R_TOO_LARGE);
    return 0;
  }

  if (max_out_len < in_len + gcm_ctx->tag_len) {
    OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_seal, CIPHER_R_BUFFER_TOO_SMALL);
    return 0;
  }

  memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
  CRYPTO_gcm128_setiv(&gcm, nonce, nonce_len);

  if (ad_len > 0 && !CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
    return 0;
  }

  if (gcm_ctx->ctr) {
    if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, in + bulk, out + bulk, in_len - bulk,
                                     gcm_ctx->ctr)) {
      return 0;
    }
  } else {
    if (!CRYPTO_gcm128_encrypt(&gcm, in + bulk, out + bulk, in_len - bulk)) {
      return 0;
    }
  }

  CRYPTO_gcm128_tag(&gcm, out + in_len, gcm_ctx->tag_len);
  *out_len = in_len + gcm_ctx->tag_len;
  return 1;
}
Exemplo n.º 10
0
int evp_aead_aes_gcm_seal(const void *ctx_buf, uint8_t *out, size_t *out_len,
                          size_t max_out_len, const uint8_t *nonce,
                          const uint8_t *in, size_t in_len, const uint8_t *ad,
                          size_t ad_len) {
  aead_assert_open_seal_preconditions(alignof(struct aead_aes_gcm_ctx), ctx_buf,
                                      out, out_len, nonce, in, in_len, ad,
                                      ad_len);

  const struct aead_aes_gcm_ctx *gcm_ctx = ctx_buf;

  if (!aead_seal_out_max_out_in_tag_len(out_len, max_out_len, in_len,
                                        EVP_AEAD_AES_GCM_TAG_LEN)) {
    /* |aead_seal_out_max_out_in_tag_len| already called |OPENSSL_PUT_ERROR|. */
    return 0;
  }

  GCM128_CONTEXT gcm;

  const AES_KEY *key = &gcm_ctx->ks.ks;

  memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
  CRYPTO_gcm128_set_96_bit_iv(&gcm, key, nonce);

  if (ad_len > 0 && !CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
    return 0;
  }

  if (gcm_ctx->ctr) {
    if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, in, out, in_len, gcm_ctx->ctr)) {
      return 0;
    }
  } else {
    if (!CRYPTO_gcm128_encrypt(&gcm, key, in, out, in_len)) {
      return 0;
    }
  }

  CRYPTO_gcm128_tag(&gcm, out + in_len, EVP_AEAD_AES_GCM_TAG_LEN);
  return 1;
}
Exemplo n.º 11
0
static int
aead_aes_gcm_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, size_t *out_len,
    size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
    const unsigned char *in, size_t in_len, const unsigned char *ad,
    size_t ad_len)
{
	const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
	GCM128_CONTEXT gcm;
	size_t bulk = 0;

	if (max_out_len < in_len + gcm_ctx->tag_len) {
		EVPerr(EVP_F_AEAD_AES_GCM_SEAL, EVP_R_BUFFER_TOO_SMALL);
		return 0;
	}

	memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
	CRYPTO_gcm128_setiv(&gcm, nonce, nonce_len);

	if (ad_len > 0 && CRYPTO_gcm128_aad(&gcm, ad, ad_len))
		return 0;

	if (gcm_ctx->ctr) {
		if (CRYPTO_gcm128_encrypt_ctr32(&gcm, in + bulk, out + bulk,
		    in_len - bulk, gcm_ctx->ctr))
			return 0;
	} else {
		if (CRYPTO_gcm128_encrypt(&gcm, in + bulk, out + bulk,
		    in_len - bulk))
			return 0;
	}

	CRYPTO_gcm128_tag(&gcm, out + in_len, gcm_ctx->tag_len);
	*out_len = in_len + gcm_ctx->tag_len;

	return 1;
}
Exemplo n.º 12
0
static int aead_aes_gcm_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out,
                                     uint8_t *out_tag, size_t *out_tag_len,
                                     size_t max_out_tag_len,
                                     const uint8_t *nonce, size_t nonce_len,
                                     const uint8_t *in, size_t in_len,
                                     const uint8_t *extra_in,
                                     size_t extra_in_len,
                                     const uint8_t *ad, size_t ad_len) {
  const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;

  if (extra_in_len + ctx->tag_len < ctx->tag_len) {
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
    return 0;
  }
  if (max_out_tag_len < extra_in_len + ctx->tag_len) {
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
    return 0;
  }
  if (nonce_len == 0) {
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
    return 0;
  }

  const AES_KEY *key = &gcm_ctx->ks.ks;

  GCM128_CONTEXT gcm;
  OPENSSL_memset(&gcm, 0, sizeof(gcm));
  OPENSSL_memcpy(&gcm.gcm_key, &gcm_ctx->gcm_key, sizeof(gcm.gcm_key));
  CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len);

  if (ad_len > 0 && !CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
    return 0;
  }

  if (gcm_ctx->ctr) {
    if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, in, out, in_len,
                                     gcm_ctx->ctr)) {
      return 0;
    }
  } else {
    if (!CRYPTO_gcm128_encrypt(&gcm, key, in, out, in_len)) {
      return 0;
    }
  }

  if (extra_in_len) {
    if (gcm_ctx->ctr) {
      if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, extra_in, out_tag,
                                       extra_in_len, gcm_ctx->ctr)) {
        return 0;
      }
    } else {
      if (!CRYPTO_gcm128_encrypt(&gcm, key, extra_in, out_tag, extra_in_len)) {
        return 0;
      }
    }
  }

  CRYPTO_gcm128_tag(&gcm, out_tag + extra_in_len, ctx->tag_len);
  *out_tag_len = ctx->tag_len + extra_in_len;

  return 1;
}
Exemplo n.º 13
0
static int32_t create_format_v1(unsigned char *wire,
				loc_t *loc,
				struct crypt_inode_info *info,
				struct master_cipher_info *master)
{
	int32_t ret;
	struct mtd_format_v1 *fmt;
	unsigned char mtd_key[16];
	AES_KEY EMTD_KEY;
	unsigned char nmtd_link_key[16];
	uint32_t ad;
	GCM128_CONTEXT *gctx;

	fmt = (struct mtd_format_v1 *)wire;

	fmt->minor_id = info->nr_minor;
	fmt->alg_id = AES_CIPHER_ALG;
	fmt->dkey_factor = master->m_dkey_size >> KEY_FACTOR_BITS;
	fmt->block_bits = master->m_block_bits;
	fmt->mode_id = master->m_mode;
	/*
	 * retrieve keys for the parts of metadata
	 */
	ret = get_emtd_file_key(info, master, mtd_key);
	if (ret)
		return ret;
	ret = get_nmtd_link_key(loc, master, nmtd_link_key);
	if (ret)
		return ret;
	
	AES_set_encrypt_key(mtd_key, sizeof(mtd_key)*8, &EMTD_KEY);

	gctx = CRYPTO_gcm128_new(&EMTD_KEY, (block128_f)AES_encrypt);

	/* TBD: Check return values */

	CRYPTO_gcm128_setiv(gctx, info->oid, sizeof(uuid_t));

	ad = htole32(MTD_LOADER_V1);
	ret = CRYPTO_gcm128_aad(gctx, (const unsigned char *)&ad, sizeof(ad));
	if (ret) {
		gf_log("crypt", GF_LOG_ERROR, " CRYPTO_gcm128_aad failed");
		CRYPTO_gcm128_release(gctx);
		return ret;
	}
	ret = CRYPTO_gcm128_encrypt(gctx,
				    get_EMTD_V1(fmt),
				    get_EMTD_V1(fmt),
				    SIZE_OF_EMTD_V1);
	if (ret) {
		gf_log("crypt", GF_LOG_ERROR, " CRYPTO_gcm128_encrypt failed");
		CRYPTO_gcm128_release(gctx);
		return ret;
	}
	/*
	 * set MAC of encrypted part of metadata
	 */
	CRYPTO_gcm128_tag(gctx, get_EMTD_V1_MAC(fmt), SIZE_OF_EMTD_V1_MAC);
	CRYPTO_gcm128_release(gctx);
	/*
	 * set the first MAC of non-encrypted part of metadata 
	 */
	return create_link_mac_v1(fmt, 0, loc, info, master);
}
static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
                          size_t len) {
  EVP_AES_GCM_CTX *gctx = ctx->cipher_data;

  /* If not set up, return error */
  if (!gctx->key_set) {
    return -1;
  }
  if (!gctx->iv_set) {
    return -1;
  }

  if (in) {
    if (out == NULL) {
      if (!CRYPTO_gcm128_aad(&gctx->gcm, in, len)) {
        return -1;
      }
    } else if (ctx->encrypt) {
      if (gctx->ctr) {
        size_t bulk = 0;
#if defined(AES_GCM_ASM)
        if (len >= 32 && AES_GCM_ASM(gctx)) {
          size_t res = (16 - gctx->gcm.mres) % 16;

          if (!CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res)) {
            return -1;
          }

          bulk = AES_gcm_encrypt(in + res, out + res, len - res, gctx->gcm.key,
                                 gctx->gcm.Yi.c, gctx->gcm.Xi.u);
          gctx->gcm.len.u[1] += bulk;
          bulk += res;
        }
#endif
        if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, in + bulk, out + bulk,
                                        len - bulk, gctx->ctr)) {
          return -1;
        }
      } else {
        size_t bulk = 0;
        if (!CRYPTO_gcm128_encrypt(&gctx->gcm, in + bulk, out + bulk,
                                  len - bulk)) {
          return -1;
        }
      }
    } else {
      if (gctx->ctr) {
        size_t bulk = 0;
#if defined(AES_GCM_ASM)
        if (len >= 16 && AES_GCM_ASM(gctx)) {
          size_t res = (16 - gctx->gcm.mres) % 16;

          if (!CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res)) {
            return -1;
          }

          bulk = AES_gcm_decrypt(in + res, out + res, len - res, gctx->gcm.key,
                                 gctx->gcm.Yi.c, gctx->gcm.Xi.u);
          gctx->gcm.len.u[1] += bulk;
          bulk += res;
        }
#endif
        if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, in + bulk, out + bulk,
                                        len - bulk, gctx->ctr)) {
          return -1;
        }
      } else {
        size_t bulk = 0;
        if (!CRYPTO_gcm128_decrypt(&gctx->gcm, in + bulk, out + bulk,
                                  len - bulk)) {
          return -1;
        }
      }
    }
    return len;
  } else {
    if (!ctx->encrypt) {
      if (gctx->taglen < 0 ||
          !CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen) != 0) {
        return -1;
      }
      gctx->iv_set = 0;
      return 0;
    }
    CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
    gctx->taglen = 16;
    /* Don't reuse the IV */
    gctx->iv_set = 0;
    return 0;
  }
}
Exemplo n.º 15
0
static int
aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
    const unsigned char *in, size_t len)
{
	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
	int rv = -1;

	/* Encrypt/decrypt must be performed in place */
	if (out != in ||
	    len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
		return -1;

	/* Set IV from start of buffer or generate IV and write to start
	 * of buffer.
	 */
	if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ?
	    EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV,
	    EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
		goto err;

	/* Use saved AAD */
	if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len))
		goto err;

	/* Fix buffer and length to point to payload */
	in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
	out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
	len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
	if (ctx->encrypt) {
		/* Encrypt payload */
		if (gctx->ctr) {
			if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, in, out,
			    len, gctx->ctr))
				goto err;
		} else {
			if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
				goto err;
		}
		out += len;

		/* Finally write tag */
		CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
		rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
	} else {
		/* Decrypt */
		if (gctx->ctr) {
			if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, in, out,
			    len, gctx->ctr))
				goto err;
		} else {
			if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
				goto err;
		}
		/* Retrieve tag */
		CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, EVP_GCM_TLS_TAG_LEN);

		/* If tag mismatch wipe buffer */
		if (memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN)) {
			explicit_bzero(out, len);
			goto err;
		}
		rv = len;
	}

err:
	gctx->iv_set = 0;
	gctx->tls_aad_len = -1;
	return rv;
}