OpenSSL 3.0 Create EC Private Key in PEM Format from Private Key in mpi repräsentation - c

I want to update a function which should generate an EC Private Key in PEM format to OpenSSL 3.0. Most of the EC functions that are used are now deprecated. Below you can see the deprecated function.
ERR Security_GetECKey(KeyPairECType enKeyPairECType, const unsigned char *puchKey, unsigned int uiLength, char **ppstPEMKey)
{
ERR err;
int iNID;
BIGNUM *pBigNumPrivate;
BN_CTX *pBigNumCtx;
EC_KEY *pEcKey;
EC_POINT *pEcPoint;
const EC_GROUP *pEcGroup;
EVP_PKEY *pEVPPKey;
int iBIOLength;
BIO *pBIOOut;
const unsigned char *puchPEMKey;
err = ERR_NONE;
if((enKeyPairECType > KeyPairECType_Max) ||
(ppstPEMKey == NULL) ||
(uiLength == 0) ||
(puchKey == NULL))
{
err = Err_Code(ERR_INVALID_PARAM);
}
else
{
switch(enKeyPairECType)
{
case KeyPairECType_NID_SECP521r1:
iNID = NID_secp521r1;
break;
default:
iNID = 0;
err = Err_Code(ERR_INVALID_PARAM);
break;
}
if(err == ERR_NONE)
{
THREAD_LOCK_LIB_TOOLS();
/*
* Use length from mpi header + 4. instead of length of whole char array.
* Length of char array (uiLength) could be longer than mpi
*/
pBigNumPrivate = BN_mpi2bn((unsigned char*)puchKey, ((puchKey[0]<<24) | (puchKey[1]<<16) | (puchKey[2]<<8) | puchKey[3]) + 4, NULL);
if(pBigNumPrivate != NULL)
{
pBigNumCtx = BN_CTX_new();
if(pBigNumCtx != NULL)
{
/*
* TODO: The low-level EC_KEY_... API functions are deprecated with OpenSSL 3.0!
* Ignore the warnings for now until the source code is adapted to use
* the appropriate high-level APIs.
*/
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
pEcKey = EC_KEY_new_by_curve_name(iNID);
if(pEcKey != NULL)
{
pEcGroup = EC_KEY_get0_group(pEcKey);
if(pEcGroup != NULL)
{
pEcPoint = EC_POINT_new(pEcGroup);
if(pEcPoint != NULL)
{
if(EC_KEY_set_private_key(pEcKey, pBigNumPrivate) != FALSE)
{
if(EC_POINT_mul(pEcGroup, pEcPoint, pBigNumPrivate, NULL, NULL, pBigNumCtx) != FALSE)
{
if(EC_KEY_set_public_key(pEcKey, pEcPoint) != FALSE)
{
pEVPPKey = EVP_PKEY_new();
if(pEVPPKey != NULL)
{
if(EVP_PKEY_set1_EC_KEY(pEVPPKey, pEcKey) != FALSE)
{
pBIOOut = BIO_new(BIO_s_mem());
if(pBIOOut != NULL)
{
gstPassword = NULL;
if((PEM_write_bio_PrivateKey(pBIOOut, pEVPPKey, NULL, NULL, 0, Security_PEM_Password_CB, NULL)) == 0)
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
else
{
iBIOLength = BIO_get_mem_data(pBIOOut, &puchPEMKey);
if(iBIOLength > 0)
{
err = Mem_AllocEx((void **)ppstPEMKey, (iBIOLength + 1) * sizeof(char));
if(err == ERR_NONE)
{
memcpy(*ppstPEMKey, puchPEMKey, iBIOLength);
(*ppstPEMKey)[iBIOLength] = '\00';
}
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
}
BIO_free(pBIOOut);
}
EVP_PKEY_free(pEVPPKey);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
EC_KEY_free(pEcKey);
}
/*
* TODO: Remove end of #pragma above if adapted!
*/
#pragma GCC diagnostic pop
BN_CTX_free(pBigNumCtx);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
BN_free(pBigNumPrivate);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
THREAD_UNLOCK_LIB_TOOLS();
}
}
return err;
}
I have tried to replace the deprecated EC functions with the EVP key functions supported by OpenSSL 3.0. Here is my latest attempt:
ERR Security_GetECKey(KeyPairECType enKeyPairECType, const unsigned char *puchKey, unsigned int uiLength, char **ppstPEMKey)
{
ERR err;
THREAD_INIT_LOCK_LIB_TOOLS();
err = ERR_NONE;
if((enKeyPairECType > KeyPairECType_Max) ||
(ppstPEMKey == NULL) ||
(uiLength == 0) ||
(puchKey == NULL))
{
err = Err_Code(ERR_INVALID_PARAM);
}
else
{
const char *pstCurveName;
switch(enKeyPairECType)
{
case KeyPairECType_NID_SECP521r1:
pstCurveName = SN_secp521r1;
break;
default:
pstCurveName = NULL;
err = Err_Code(ERR_INVALID_PARAM);
break;
}
if(err == ERR_NONE)
{
BIGNUM *pBigNumPrivate;
THREAD_LOCK_LIB_TOOLS();
/*
* Use length from mpi header + 4. instead of length of whole char array.
* Length of char array (uiLength) could be longer than mpi
*/
pBigNumPrivate = BN_mpi2bn((unsigned char *) puchKey, ((puchKey[0] << 24) | (puchKey[1] << 16) | (puchKey[2] << 8) | puchKey[3]) + 4, NULL);
if(pBigNumPrivate != NULL)
{
int iNid = OBJ_sn2nid(pstCurveName);
if(iNid != NID_undef)
{
EC_GROUP *pEcGroup = EC_GROUP_new_by_curve_name(iNid);
if(pEcGroup != NULL)
{
EC_POINT *pEcPoint = EC_POINT_new(pEcGroup);
BN_CTX *pBigNumCtx = BN_CTX_new();
if((pEcPoint != NULL) && (pBigNumCtx != NULL) && EC_POINT_mul(pEcGroup, pEcPoint, pBigNumPrivate, NULL, NULL, pBigNumCtx))
{
size_t uzPubKeySize = EC_POINT_point2oct(pEcGroup, pEcPoint, POINT_CONVERSION_COMPRESSED, NULL, 0, NULL);
if(uzPubKeySize > 0)
{
unsigned char *puchPubKey = NULL;
err = Mem_AllocEx((void **) &puchPubKey, uzPubKeySize);
if((err == ERR_NONE) && (EC_POINT_point2oct(pEcGroup, pEcPoint, POINT_CONVERSION_COMPRESSED, puchPubKey, uzPubKeySize, NULL)))
{
OSSL_PARAM_BLD *paramBuild = OSSL_PARAM_BLD_new();
if((paramBuild != NULL) &&
OSSL_PARAM_BLD_push_utf8_string(paramBuild, OSSL_PKEY_PARAM_GROUP_NAME, pstCurveName, 0) &&
OSSL_PARAM_BLD_push_BN(paramBuild, OSSL_PKEY_PARAM_PRIV_KEY, pBigNumPrivate) &&
OSSL_PARAM_BLD_push_octet_ptr(paramBuild, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, puchPubKey, uzPubKeySize))
{
EVP_PKEY *pEVPPKey = NULL;
OSSL_PARAM *pParams = OSSL_PARAM_BLD_to_param(paramBuild);
EVP_PKEY_CTX *pKeyCtx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
if((pParams != NULL) &&
(pKeyCtx != NULL) &&
(EVP_PKEY_fromdata_init(pKeyCtx) > 0) &&
((EVP_PKEY_fromdata(pKeyCtx, &pEVPPKey, EVP_PKEY_KEYPAIR, pParams)) > 0))
{
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pEVPPKey, NULL);
if(EVP_PKEY_check(ctx) <= 0)
ERR_print_errors_fp(stderr);
BIO *pBIOOut = BIO_new(BIO_s_mem());
if(pBIOOut != NULL)
{
if((PEM_write_bio_PrivateKey(pBIOOut, pEVPPKey, NULL, NULL, 0, NULL, NULL)) == 0)
{
ERR_print_errors_fp(stderr);
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
else
{
const unsigned char *puchPEMKey;
int iBIOLength = BIO_get_mem_data(pBIOOut, &puchPEMKey);
if(iBIOLength > 0)
{
err = Mem_AllocEx((void **) ppstPEMKey, (iBIOLength + 1) * sizeof(char));
if(err == ERR_NONE)
{
memcpy(*ppstPEMKey, puchPEMKey, iBIOLength);
(*ppstPEMKey)[iBIOLength] = '\00';
}
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
}
BIO_free(pBIOOut);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
EVP_PKEY_free(pEVPPKey);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
EVP_PKEY_CTX_free(pKeyCtx);
OSSL_PARAM_free(pParams);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
OSSL_PARAM_BLD_free(paramBuild);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
Mem_Free((void **) &puchPubKey);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
EC_POINT_free(pEcPoint);
BN_CTX_free(pBigNumCtx);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
EC_GROUP_free(pEcGroup);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
BN_free(pBigNumPrivate);
}
else
{
err = Err_Code(ERR_TOOLS_SECURITY_GET_EC_KEY);
}
THREAD_UNLOCK_LIB_TOOLS();
}
return err;
}
It looks like I am not creating all the parameters of the EVP structure that are necessary to create the PEM key.
The check after the key generation returns the following error:
C01BFCF7FF7F0000:error:080C0102:elliptic curve routines:ossl_ec_key_public_check_quick:passed a null parameter:crypto/ec/ec_key.c:444:
After PEM_write_bio_PrivateKey, the following errors are finally output:
C01BFCF7FF7F0000:error:080C0102:elliptic curve routines:i2d_ECPrivateKey:passed a null parameter:crypto/ec/ec_asn1.c:1031:
C01BFCF7FF7F0000:error:1C8C0100:Provider routines:key_to_p8info:malloc failure:providers/implementations/encode_decode/encode_key2any.c:94:
I'm running out of ideas and the OpenSSL man page isn't really helpful, can someone help me out?

Related

OpenSSL bad hostname lookup Windows C

I am trying to get the SSL/TLS client with OpenSSL from here: https://wiki.openssl.org/index.php/SSL/TLS_Client to build and run in visual studio.
I have it successfully building in visual studio, but it won't run successfully.
Currently it will run to res = BIO_do_connect(web); andssl_err = ERR_get_error(); eventually failing at the following if (!(1 == res)) the console output is bad hostname lookup
I've looked around to try and find some solution, but nothing seems effective.
The H file I'm using is pretty much the same as the one at the openssl.org. with the exception of the addition of
typedef struct {
int status_code;
char *reason;
char *content;
} HttpResponse;
This is pretty much my first run in C, I've done Java before, so if someone has any insight, that would be great. Or if they can point to an example of an https post request for Windows in C.
#include "openssl-bio-fetch.h"
#include "corecrt_wstdio.h"
#ifndef HEADER_X509_H
#include <openssl/x509.h>
/* openssl/x509.h ends up #include-ing this file at about the only
* appropriate moment. */
#endif
int verify_callback(int preverify, X509_STORE_CTX* x509_ctx);
void init_openssl_library(void);
void print_cn_name(const char* label, X509_NAME* const name);
void print_san_name(const char* label, X509* const cert);
void print_error_string(unsigned long err, const char* const label);
const char* const PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!SRP:!PSK:!CAMELLIA:!RC4:!MD5:!DSS";
#if 0
const char* const PREFERRED_CIPHERS = "kEECDH:kEDH:kRSA:AESGCM:AES256:AES128:3DES:SHA256:SHA84:SHA1:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM!ADH:!AECDH";
#endif
#if 0
const char* const PREFERRED_CIPHERS = NULL;
#endif
#if 0
const char* PREFERRED_CIPHERS =
/* TLS 1.2 only */
"ECDHE-ECDSA-AES256-GCM-SHA384:"
"ECDHE-RSA-AES256-GCM-SHA384:"
"ECDHE-ECDSA-AES128-GCM-SHA256:"
"ECDHE-RSA-AES128-GCM-SHA256:"
/* TLS 1.2 only */
"DHE-DSS-AES256-GCM-SHA384:"
"DHE-RSA-AES256-GCM-SHA384:"
"DHE-DSS-AES128-GCM-SHA256:"
"DHE-RSA-AES128-GCM-SHA256:"
/* TLS 1.0 only */
"DHE-DSS-AES256-SHA:"
"DHE-RSA-AES256-SHA:"
"DHE-DSS-AES128-SHA:"
"DHE-RSA-AES128-SHA:"
/* SSL 3.0 and TLS 1.0 */
"EDH-DSS-DES-CBC3-SHA:"
"EDH-RSA-DES-CBC3-SHA:"
"DH-DSS-DES-CBC3-SHA:"
"DH-RSA-DES-CBC3-SHA";
#endif
void add_char_header(char *current, char *key, char *value)
{
strcat(current, "\r\n");
strcat(current, key);
strcat(current, ": ");
strcat(current, value);
}
void add_int_header(char *current, char *key, int value)
{
char *buffer = malloc(5);
sprintf(buffer, "%d", value);
strcat(current, "\r\n");
strcat(current, key);
strcat(current, ": ");
strcat(current, buffer);
free(buffer);
}
void parse_http_response(char *resp, HttpResponse *response)
{
response.reason = "";
response.content = "";
}
char * buildRequest(char *request) {
size_t size;
size = strlen("{\"client_ip\":\"10.20.30.40\"}");
strcpy(request, "{\"client_ip\":\"10.20.30.40\"}");
printf("pks-368\n");
return request;
}
int
main(int ac, char **av)
{
char *request = malloc(225);
buildRequest(request);
HttpResponse response;
response.reason = calloc(1, 64);
response.content = calloc(1, 10 * 1024);
response.status_code = 0;
int a = openssl_fetch(request, &response);
fprintf(stderr, "C %d", response.status_code);
fprintf(stderr, "A %s", response.content);
fprintf(stderr, "B %s", response.reason);
printf("Paused");
}
int openssl_fetch(char *request, HttpResponse *response)
{
char *HOST_NAME = "google.com";
char *HOST_PORT = "443";
char *hostname = calloc(1, 100);
strcpy(hostname, HOST_NAME);
strcat(hostname, ":");
strcat(hostname, HOST_PORT);
long res = 1;
int ret = 1;
unsigned long ssl_err = 0;
SSL_CTX* ctx = NULL;
BIO *web = NULL, *out = NULL;
SSL *ssl = NULL;
do {
init_openssl_library();
const SSL_METHOD* method = SSLv23_method();
ssl_err = ERR_get_error();
if (!(NULL != method))
{
print_error_string(ssl_err, "SSLv23_method");
break; /* failed */
}
ctx = SSL_CTX_new(method);
ssl_err = ERR_get_error();
if (!(ctx != NULL))
{
print_error_string(ssl_err, "SSL_CTX_new");
break; /* failed */
}
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
SSL_CTX_set_verify_depth(ctx, 5);
const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
long old_opts = SSL_CTX_set_options(ctx, flags);
UNUSED(old_opts);
const char *file_loc = "C:\\Users\\$USER\\Desktop\\trusted-roots.pem";
res = SSL_CTX_load_verify_locations(ctx, file_loc, NULL);
ssl_err = ERR_get_error();
if (!(1 == res))
{
fprintf(stderr, "SSL_CTX_load_verify_locations -- [%s]\n", ssl_err);
}
web = BIO_new_ssl_connect(ctx);
ssl_err = ERR_get_error();
if (!(web != NULL))
{
print_error_string(ssl_err, "BIO_new_ssl_connect");
break; /* failed */
}
res = BIO_set_conn_hostname(web, hostname);
ssl_err = ERR_get_error();
if (!(1 == res))
{
print_error_string(ssl_err, "BIO_set_conn_hostname");
break; /* failed */
}
BIO_get_ssl(web, &ssl);
ssl_err = ERR_get_error();
if (!(ssl != NULL))
{
print_error_string(ssl_err, "BIO_get_ssl");
break; /* failed */
}
res = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);
ssl_err = ERR_get_error();
if (!(1 == res))
{
print_error_string(ssl_err, "SSL_set_cipher_list");
break; /* failed */
}
res = SSL_set_tlsext_host_name(ssl, HOST_NAME);
ssl_err = ERR_get_error();
if (!(1 == res))
{
print_error_string(ssl_err, "SSL_set_tlsext_host_name");
}
out = BIO_new_fp(stdout, BIO_NOCLOSE);
ssl_err = ERR_get_error();
if (!(NULL != out))
{
print_error_string(ssl_err, "BIO_new_fp");
break; /* failed */
}
res = BIO_do_connect(web);
ssl_err = ERR_get_error();
if (!(1 == res))
{
print_error_string(ssl_err, "BIO_do_connect");
break; /* failed */
}
res = BIO_do_handshake(web);
ssl_err = ERR_get_error();
if (!(1 == res))
{
print_error_string(ssl_err, "BIO_do_handshake");
break; /* failed */
}
X509* cert = SSL_get_peer_certificate(ssl);
if (cert) { X509_free(cert); } /* Free immediately */
if (NULL == cert)
{
print_error_string(X509_V_ERR_APPLICATION_VERIFICATION, "SSL_get_peer_certificate");
break; /* failed */
}
res = SSL_get_verify_result(ssl);
if (!(X509_V_OK == res))
{
print_error_string((unsigned long)res, "SSL_get_verify_results");
break; /* failed */
}
char message[2048];
strcpy(message, "POST ");
strcat(message, HOST_RESOURCE);
strcat(message, " HTTP/1.1 ");
add_char_header(message, "Host", HOST_NAME);
add_char_header(message, "Connection", "close");
add_char_header(message, "Accept", "*/*");
add_int_header(message, "Content-Length", (int)strlen(request));
strcat(message, "\r\n\r\n");
strcat(message, request);
BIO_puts(web, message);
char buff[6144] = { 0 };
int len = 0;
do {
len = BIO_read(web, buff, sizeof(buff));
} while (len > 0 || BIO_should_retry(web));
ret = 0;
parse_http_response(buff, response);
free(hostname);
} while (0);
if (out)
BIO_free(out);
if (web != NULL)
BIO_free_all(web);
if (NULL != ctx)
SSL_CTX_free(ctx);
return ret;
}
void init_openssl_library(void)
{
(void)SSL_library_init();
SSL_load_error_strings();
#if defined (OPENSSL_THREADS)
// fprintf(stdout, "Warning: thread locking is not implemented\n");
#endif
}
void print_cn_name(const char* label, X509_NAME* const name)
{
int idx = -1, success = 0;
unsigned char *utf8 = NULL;
do
{
if (!name) break; /* failed */
idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
if (!(idx > -1)) break; /* failed */
X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx);
if (!entry) break; /* failed */
ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
if (!data) break; /* failed */
int length = ASN1_STRING_to_UTF8(&utf8, data);
if (!utf8 || !(length > 0)) break; /* failed */
fprintf(stdout, " %s: %s\n", label, utf8);
success = 1;
} while (0);
if (utf8)
OPENSSL_free(utf8);
if (!success)
fprintf(stdout, " %s: <not available>\n", label);
}
void print_san_name(const char* label, X509* const cert)
{
int success = 0;
GENERAL_NAMES* names = NULL;
unsigned char* utf8 = NULL;
do
{
if (!cert) break; /* failed */
names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
if (!names) break;
int i = 0, count = sk_GENERAL_NAME_num(names);
if (!count) break; /* failed */
for (i = 0; i < count; ++i)
{
GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
if (!entry) continue;
if (GEN_DNS == entry->type)
{
int len1 = 0, len2 = -1;
len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
if (utf8) {
len2 = (int)strlen((const char*)utf8);
}
if (len1 != len2) {
fprintf(stderr, " Strlen and ASN1_STRING size do not match (embedded null?): %d vs %d\n", len2, len1);
}
if (utf8 && len1 && len2 && (len1 == len2)) {
fprintf(stdout, " %s: %s\n", label, utf8);
success = 1;
}
if (utf8) {
OPENSSL_free(utf8), utf8 = NULL;
}
}
else
{
fprintf(stderr, " Unknown GENERAL_NAME type: %d\n", entry->type);
}
}
} while (0);
if (names)
GENERAL_NAMES_free(names);
if (utf8)
OPENSSL_free(utf8);
if (!success)
fprintf(stdout, " %s: <not available>\n", label);
}
int verify_callback(int preverify, X509_STORE_CTX* x509_ctx)
{
int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
int err = X509_STORE_CTX_get_error(x509_ctx);
if (depth == 0) {
}
if (preverify == 0)
{
if (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
fprintf(stdout, " Error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY\n");
else if (err == X509_V_ERR_CERT_UNTRUSTED)
fprintf(stdout, " Error = X509_V_ERR_CERT_UNTRUSTED\n");
else if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)
fprintf(stdout, " Error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN\n");
else if (err == X509_V_ERR_CERT_NOT_YET_VALID)
fprintf(stdout, " Error = X509_V_ERR_CERT_NOT_YET_VALID\n");
else if (err == X509_V_ERR_CERT_HAS_EXPIRED)
fprintf(stdout, " Error = X509_V_ERR_CERT_HAS_EXPIRED\n");
else if (err == X509_V_OK)
fprintf(stdout, " Error = X509_V_OK\n");
else
fprintf(stdout, " Error = %d\n", err);
}
#if !defined(NDEBUG)
return 1;
#else
return preverify;
#endif
}
void print_error_string(unsigned long err, const char* const label)
{
const char* const str = ERR_reason_error_string(err);
if (str)
fprintf(stderr, "%s\n", str);
else
fprintf(stderr, "%s failed: %lu (0x%lx)\n", label, err, err);
}

How to set l2tp preshared key?

I need to create RASENTRY for L2TP with pre-shared key set. So far, I can see that entry has somewhat correct flags, but no key is set, unfortunately.
Here is code:
int common_ras_manager_create_entry(const char* server_address, const char* username, const char* password, MY_VPN_CONNECTION_TYPE connection_type, const char* preshared_key)
{
DWORD EntryInfoSize = 0;
DWORD DeviceInfoSize = 0;
DWORD Ret;
LPRASENTRY lpRasEntry;
LPBYTE lpDeviceInfo;
// Get buffer sizing information for a default phonebook entry
if ((Ret = RasGetEntryProperties(NULL, "", NULL, &EntryInfoSize, lpDeviceInfo, &DeviceInfoSize)) != 0)
{
if (Ret != ERROR_BUFFER_TOO_SMALL)
{
printf("RasGetEntryProperties sizing failed with error %d\n", Ret);
return Ret;
}
}
lpRasEntry = (LPRASENTRY) GlobalAlloc(GPTR, EntryInfoSize);
if (DeviceInfoSize == 0)
lpDeviceInfo = NULL;
else
lpDeviceInfo = (LPBYTE) GlobalAlloc(GPTR, DeviceInfoSize);
// Get default phonebook entry
lpRasEntry->dwSize = sizeof(RASENTRY);
if ((Ret = RasGetEntryProperties(NULL, "", lpRasEntry, &EntryInfoSize, lpDeviceInfo, &DeviceInfoSize)) != 0)
{
printf("RasGetEntryProperties failed with error %d\n", Ret);
return Ret;
}
// Validate new phonebook name "Testentry"
if ((Ret = RasValidateEntryName(NULL, APP_NAME)) != ERROR_SUCCESS)
{
printf("RasValidateEntryName failed with error %d\n", Ret);
if (Ret != ERROR_ALREADY_EXISTS)
return Ret;
}
LPRASDEVINFO ras_devices;
DWORD cb =sizeof(RASDEVINFO);
DWORD cbDevices = 0;
ras_devices = (LPRASDEVINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
if (NULL == ras_devices)
{
printf("HeapAlloc failed.\n");
return ERROR_OUTOFMEMORY;
}
ras_devices->dwSize = sizeof(RASDEVINFO);
if ((Ret = RasEnumDevices(ras_devices, &cb, &cbDevices)) != ERROR_SUCCESS)
{
printf("RasEnumDevices failed with error %d\n", Ret);
switch(Ret)
{
case ERROR_BUFFER_TOO_SMALL:
printf("buffer too small");
HeapFree(GetProcessHeap(), 0, (LPVOID)ras_devices);
ras_devices = (LPRASDEVINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
if (NULL == ras_devices)
{
printf("HeapAlloc failed.\n");
return ERROR_OUTOFMEMORY;
}
ras_devices->dwSize = sizeof(RASDEVINFO);
Ret = RasEnumDevices(ras_devices, &cb, &cbDevices);
if (ERROR_SUCCESS == Ret)
{
//fSuccess = TRUE;
}
else
{
printf("RasEnumDevices failed again: Error = %d\n", Ret);
return Ret;
//goto done;
}
break;
case ERROR_NOT_ENOUGH_MEMORY:
printf("ERROR_NOT_ENOUGH_MEMORY");
return Ret;
break;
case ERROR_INVALID_PARAMETER:
printf("ERROR_INVALID_PARAMETER");
return Ret;
break;
case ERROR_INVALID_USER_BUFFER:
printf("ERROR_INVALID_USER_BUFFER");
return Ret;
break;
}
}
DWORD dwVpnStrategy = 0;
char device_name_mask[5];
strcpy(device_name_mask, "");
gboolean preshared_key_valid = 0;
switch(connection_type)
{
case PPTP:
strcpy(device_name_mask, "PPTP");
dwVpnStrategy = VS_PptpOnly;
break;
case L2TP:
if (preshared_key == 0 || strlen(preshared_key) == 0)
{
printf("CRITICAL: preshared key not set.");
return 1;
}
else
{
preshared_key_valid = TRUE;
}
strcpy(device_name_mask, "L2TP");
dwVpnStrategy = VS_L2tpOnly;
break;
}
int i =0;
for (i = 0; i < cbDevices; i++)
{
RASDEVINFO r = ras_devices[i];
if (strstr(r.szDeviceName, device_name_mask))
{
break;
}
}
//lpRasEntry->dwfOptions |= RASEO_SpecificIpAddr;
//lpRasEntry->szLocalPhoneNumber = RASDT_Vpn;
lpRasEntry->dwfNetProtocols |= RASNP_Ip;
lpRasEntry->dwFramingProtocol = RASFP_Ppp;
lstrcpy(lpRasEntry->szDeviceType, RASDT_Vpn);
lstrcpy(lpRasEntry->szDeviceName, ras_devices[i].szDeviceName);
lstrcpy(lpRasEntry->szLocalPhoneNumber, server_address);
lpRasEntry->dwVpnStrategy = dwVpnStrategy; // VS_PptpOnly; VS_SstpOnly
if (preshared_key_valid)
{
L2TP_CONFIG_DATA* data = GlobalAlloc(GPTR, sizeof(L2TP_CONFIG_DATA));
lpRasEntry->dwfOptions2 |= RASEO2_UsePreSharedKey;
data->dwOffsetKey = 16;
memcpy((PBYTE)data + data->dwOffsetKey, preshared_key, strlen(preshared_key));
data->dwAuthType =L2TP_IPSEC_AUTH_PRESHAREDKEY;
RasSetCustomAuthData(NULL, APP_NAME, data, sizeof(L2TP_CONFIG_DATA));
}
if ((Ret = RasSetEntryProperties(NULL, APP_NAME, lpRasEntry, EntryInfoSize, lpDeviceInfo, DeviceInfoSize)) != 0)
{
printf("RasSetEntryProperties failed with error %d\n", Ret);
return Ret;
}
//if ((Ret = RasSetCredentials(NULL, lpRasEntry.))
}
I cant find where is buffer to fill for pre-shared key.
Following code works fine.
// l2tp
if (preshared_key_valid)
{
RASCREDENTIALS ras_cre_psk = {0};
ras_cre_psk.dwSize = sizeof(ras_cre_psk);
ras_cre_psk.dwMask = 0x00000010; //RASCM_PreSharedKey;
wcscpy(ras_cre_psk.szPassword, preshared_key);
if ((Ret = RasSetCredentials(NULL, APP_NAME, &ras_cre_psk, FALSE)))
{
printf("RasSetCredentials failed with error %d\n", Ret);
return Ret;
}
}

"bad packet length" error after updating to OpenSSL 0.9.8.zf

I was using OpenSSL version 0.9.8h in an Android project. I update it to the 0.9.8.zf version but now it doesn't work.
The two functions that highlight the problem are initialize_client_ctx and initialize_client_ctx. When I call SSL_connect I get an SSL_ERROR_SSL error value. By checking details I retrieve a "bad packet length" error (error:14092073:SSL routines:SSL3_GET_SERVER_HELLO:bad packet length).
The point in the code is indicated in a comment. The code works well with the previous version. I attach also a Wireshark capture file. Any ideas?
SSL_CTX *initialize_client_ctx(const char *keyfile, const char *certfile,
const char *password, int transport)
{
SSL_METHOD *meth = NULL;
X509 *cert = NULL;
SSL_CTX *ctx;
if (transport == IPPROTO_UDP) {
meth = DTLSv1_client_method();
} else if (transport == IPPROTO_TCP) {
meth = TLSv1_client_method();
} else {
return NULL;
}
ctx = SSL_CTX_new(meth);
if (ctx == NULL) {
//print ... Couldn't create SSL_CTX
return NULL;
}
if (password[0] != '\0') {
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) password);
SSL_CTX_set_default_passwd_cb(ctx, password_cb);
}
if (tls_client_local_cn_name[0] != '\0') {
cert = _tls_set_certificate(ctx, tls_client_local_cn_name);
}
if (cert==NULL && certfile[0] != '\0') {
//print several warnings....
}
if (cert!=NULL)
{
X509_free(cert);
cert = NULL;
}
/* Load the CAs we trust */
{
char *caFile = 0, *caFolder = 0;
int fd = open(eXosip_tls_ctx_params.root_ca_cert, O_RDONLY);
if (fd >= 0) {
struct stat fileStat;
if (fstat(fd, &fileStat) < 0) {
} else {
if (S_ISDIR(fileStat.st_mode)) {
caFolder = eXosip_tls_ctx_params.root_ca_cert;
} else {
caFile = eXosip_tls_ctx_params.root_ca_cert;
}
}
close(fd);
}
{
int verify_mode = SSL_VERIFY_PEER;
SSL_CTX_set_verify(ctx, verify_mode, &verify_cb);
SSL_CTX_set_verify_depth(ctx, ex_verify_depth + 1);
}
}
SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
SSL_OP_CIPHER_SERVER_PREFERENCE);
if(!SSL_CTX_set_cipher_list(ctx,"ALL")) {
//print ... set_cipher_list: cannot set anonymous DH cipher
SSL_CTX_free(ctx);
return NULL;
}
return ctx;
}
static int _tls_tl_ssl_connect_socket(struct socket_tab *sockinfo)
{
X509 *cert;
BIO *sbio;
int res;
if (sockinfo->ssl_ctx == NULL) {
sockinfo->ssl_ctx =
initialize_client_ctx(eXosip_tls_ctx_params.client.priv_key,
eXosip_tls_ctx_params.client.cert,
eXosip_tls_ctx_params.client.priv_key_pw,
IPPROTO_TCP);
sockinfo->ssl_conn = SSL_new(sockinfo->ssl_ctx);
if (sockinfo->ssl_conn == NULL) {
return -1;
}
sbio = BIO_new_socket(sockinfo->socket, BIO_NOCLOSE);
if (sbio == NULL) {
return -1;
}
SSL_set_bio(sockinfo->ssl_conn, sbio, sbio);
}
do {
struct timeval tv;
int fd;
fd_set readfds;
res = SSL_connect(sockinfo->ssl_conn);
res = SSL_get_error(sockinfo->ssl_conn, res);
if (res == SSL_ERROR_NONE) {
//printf... SSL_connect succeeded
break;
}
if (res != SSL_ERROR_WANT_READ && res != SSL_ERROR_WANT_WRITE) {
//<-- here there is a problem res == SSL_ERROR_SSL
//print ERR_reason_error_string(ERR_get_error()));
//print ERR_error_string(ERR_get_error(), NULL));
return -1;
}
tv.tv_sec = SOCKET_TIMEOUT / 1000;
tv.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
//retry the connection
fd = SSL_get_fd(sockinfo->ssl_conn);
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
res = select(fd + 1, &readfds, NULL, NULL, &tv);
if (res < 0) {
//print error
return -1;
} else if (res > 0) {
//print...connetrion done!
} else {
//socket timeout, no data to read
return 1;
}
} while (!SSL_is_init_finished(sockinfo->ssl_conn));
if (SSL_is_init_finished(sockinfo->ssl_conn)) {
//print.. SSL_is_init_finished done
} else {
//print.. failed
}
cert = SSL_get_peer_certificate(sockinfo->ssl_conn);
if (cert != 0) {
int cert_err;
tls_dump_cert_info("tls_connect: remote certificate: ", cert);
cert_err = SSL_get_verify_result(sockinfo->ssl_conn);
if (cert_err != X509_V_OK) {
//print... Failed to verify remote certificate
tls_dump_verification_failure(cert_err);
if (eXosip_tls_ctx_params.server.cert[0] != '\0') {
X509_free(cert);
return -1;
} else if (cert_err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
&& cert_err != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
&& cert_err != X509_V_ERR_CRL_HAS_EXPIRED
&& cert_err != X509_V_ERR_CERT_HAS_EXPIRED
&& cert_err != X509_V_ERR_CERT_REVOKED
&& cert_err != X509_V_ERR_CERT_UNTRUSTED
&& cert_err != X509_V_ERR_CERT_REJECTED) {
X509_free(cert);
return -1;
}
}
X509_free(cert);
} else {
//print .. No certificate received
/* X509_free is not necessary because no cert-object was created -> cert == NULL */
if (eXosip_tls_ctx_params.server.cert[0] == '\0') {
#ifdef ENABLE_ADH
/* how can we guess a user want ADH... specific APIs.. */
sockinfo->ssl_state = 3;
return 0;
#endif
}
return -1;
}
sockinfo->ssl_state = 3;
return 0;
}
SOLVED Thanks to Eric Tsui that helps me to figure out the problem. The 'hello' that I receive from the server in the handshake has zero length. To solve this I modified the file openssl/ssl/s3_clnt.c in the following way (toggling off the length control):
diff -ur ./s3_clnt.c ./original/s3_clnt.c
--- submodules/externals/openssl/ssl/s3_clnt.c 2015-06-29 14:59:56.723462992 +0200
+++ ../../opensslOrig/s3_clnt.c 2015-06-29 15:00:22.487464221 +0200
## -868,12 +868,14 ##
}
#endif
+#ifndef OPENSSL_NO_TLSEXT
if (p != (d + n)) {
/* wrong packet length */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_BAD_PACKET_LENGTH);
goto f_err;
}
+#endif
return (1);
f_err:

Not able to decode mp4 file using latest ffmpeg library : av_decode_video2

I am writing a wrapper code around latest ffmpeg library. I am supplying MP4 files from local system. My problem is that I am unable to get any decoded frames when I use av_decode_video2(). The return value comes out to be negative. I have used av_read_frame() which returns 0. I googled about the problem I am facing but no where could I find the correct explanation. Please give me insight here. Pasting the pseudo code here.
av_init_packet(avpkt);
picture=av_frame_alloc();
pFrameRGB=av_frame_alloc();
codec = avcodec_find_decoder(CODEC_ID_H264);
c= avcodec_alloc_context3(codec)
avcodec_open2(decoderLibraryData->c, decoderLibraryData->codec, NULL)
FormatContext = avformat_alloc_context();
char *pUrl ="./1.MP4";
iRet = avformat_open_input(atContext, pUrl, pFmt, NULL);
if(FormatContext == NULL)
{
printf("could not assign any memory !!!!!!!!! \n");
}
avformat_find_stream_info(FormatContext, NULL);
while(av_read_frame(FormatContext,avpkt) >= 0)
{
len = avcodec_decode_video2(c, picture, &got_picture,avpkt);
printf("CODEC MANAGER len %d Frame decompressed %d \n",len,got_picture);
if (len <= 0)
{
return ERROR;
}
}
}
if(lastHeight != 0 && lastWidth != 0)
{
if(lastWidth != c->width || lastHeight != c->height )
{
av_free(buffer);
buffer = NULL;
lastWidth = c->width;
lastHeight = c->height;
}
}
else
{
lastWidth = c->width;
lastHeight = c->height;
}
decodeFlag = 1;
if(!buffer)
{
int numBytes;
v_mutex_lock(globalCodecLock);
switch(inPixFormat)
{
case RGB:
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, c->width, c->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
avpicture_fill((AVPicture *)pFrameRGB,buffer,PIX_FMT_RGB24,c->width, c->height);
if(cntxt)
sws_freeContext(cntxt);
cntxt = sws_getContext(c->width, c->height, c->pix_fmt,
c->width, c->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
break;
}
v_mutex_unlock(globalCodecLock);
if(cntxt == NULL)
{
printf("sws_getContext error\n");
return ERROR;
}
}
{
sws_scale(cntxt, picture->data, picture->linesize, 0, c->height, pFrameRGB->data, pFrameRGB->linesize);
if(rgbBuff)
{
if(c->width <= *width && c->height <= *height)
{
saveFrame(pFrameRGB, c->width, c->height, rgbBuff,inPixFormat);
*width = c->width;
*height = c->height;
rs = SUCCESS;
break;
}
else
{
rs = VA_LOWBUFFERSIZE;
}
}
else
{
rs = VA_LOWBUFFERSIZE;
}
}
if(width)
{
*width = c->width;
}
if(height)
{
*height = c->height;
}
if(rs == VA_LOWBUFFERSIZE)
{
break;
}
I am getting the return value of av_read_frame as 0 but av_decode_video2 returns value in negative. I am not able to get any clue here.
Make sure you have called
av_register_all();
or
avcodec_register_all();
at the beginning of your app.
Also it seems the problem is from calling avformat_find_stream_info. Test with the following code:
AVPacket avpkt;
av_init_packet(&avpkt);
AVFrame* picture = av_frame_alloc();
AVFrame* pFrameRGB = av_frame_alloc();
AVFormatContext* c2 = avformat_alloc_context();
char *pUrl = "C:/Sample Videos/20-06-34.MP4";
int video_stream_index = 0;
AVInputFormat* pFmt;
int iRet = avformat_open_input(&c2, pUrl, pFmt, NULL);
AVStream* stream = c2->streams[video_stream_index];
AVCodec* codec = avcodec_find_decoder(stream->codec->codec_id);
avcodec_open2(stream->codec, codec, NULL);
if (c2 == NULL)
{
printf("could not assign any memory !!!!!!!!! \n");
}
while (av_read_frame(c2, &avpkt) >= 0)
{
int got_picture;
int len = avcodec_decode_video2(stream->codec, picture, &got_picture, &avpkt);
printf("CODEC MANAGER len %d Frame decompressed %d \n", len, got_picture);
if (len <= 0)
{
return ERROR;
}
}

Cropping Square Video using FFmpeg

Updated
So I am trying to decode a mp4 file, crop the video into a square, and then re encode it back out to another mp4 file. This is my current code but there are a few issues with it.
One is that the video doesn't keep its rotation after the video has been re encoded
Second is that the frames get outputted in a very fast video file that is not the same length as the original
Third is that there is no sound
Lastly and most importantly is do I need AVFilter to do the frame cropping or can it just be done per frame as a resize of the frame and then encoded back out.
const char *inputPath = "test.mp4";
const char *outPath = "cropped.mp4";
const char *outFileType = "mp4";
static AVFrame *oframe = NULL;
static AVFilterGraph *filterGraph = NULL;
static AVFilterContext *crop_ctx = NULL;
static AVFilterContext *buffersink_ctx = NULL;
static AVFilterContext *buffer_ctx = NULL;
int err;
int crop_video(int width, int height) {
av_register_all();
avcodec_register_all();
avfilter_register_all();
AVFormatContext *inCtx = NULL;
// open input file
err = avformat_open_input(&inCtx, inputPath, NULL, NULL);
if (err < 0) {
printf("error at open input in\n");
return err;
}
// get input file stream info
err = avformat_find_stream_info(inCtx, NULL);
if (err < 0) {
printf("error at find stream info\n");
return err;
}
// get info about video
av_dump_format(inCtx, 0, inputPath, 0);
// find video input stream
int vs = -1;
int s;
for (s = 0; s < inCtx->nb_streams; ++s) {
if (inCtx->streams[s] && inCtx->streams[s]->codec && inCtx->streams[s]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
vs = s;
break;
}
}
// check if video stream is valid
if (vs == -1) {
printf("error at open video stream\n");
return -1;
}
// set output format
AVOutputFormat * outFmt = av_guess_format(outFileType, NULL, NULL);
if (!outFmt) {
printf("error at output format\n");
return -1;
}
// get an output context to write to
AVFormatContext *outCtx = NULL;
err = avformat_alloc_output_context2(&outCtx, outFmt, NULL, NULL);
if (err < 0 || !outCtx) {
printf("error at output context\n");
return err;
}
// input and output stream
AVStream *outStrm = avformat_new_stream(outCtx, NULL);
AVStream *inStrm = inCtx->streams[vs];
// add a new codec for the output stream
AVCodec *codec = NULL;
avcodec_get_context_defaults3(outStrm->codec, codec);
outStrm->codec->thread_count = 1;
outStrm->codec->coder_type = AVMEDIA_TYPE_VIDEO;
if(outCtx->oformat->flags & AVFMT_GLOBALHEADER) {
outStrm->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
outStrm->codec->sample_aspect_ratio = outStrm->sample_aspect_ratio = inStrm->sample_aspect_ratio;
err = avio_open(&outCtx->pb, outPath, AVIO_FLAG_WRITE);
if (err < 0) {
printf("error at opening outpath\n");
return err;
}
outStrm->disposition = inStrm->disposition;
outStrm->codec->bits_per_raw_sample = inStrm->codec->bits_per_raw_sample;
outStrm->codec->chroma_sample_location = inStrm->codec->chroma_sample_location;
outStrm->codec->codec_id = inStrm->codec->codec_id;
outStrm->codec->codec_type = inStrm->codec->codec_type;
if (!outStrm->codec->codec_tag) {
if (! outCtx->oformat->codec_tag
|| av_codec_get_id (outCtx->oformat->codec_tag, inStrm->codec->codec_tag) == outStrm->codec->codec_id
|| av_codec_get_tag(outCtx->oformat->codec_tag, inStrm->codec->codec_id) <= 0) {
outStrm->codec->codec_tag = inStrm->codec->codec_tag;
}
}
outStrm->codec->bit_rate = inStrm->codec->bit_rate;
outStrm->codec->rc_max_rate = inStrm->codec->rc_max_rate;
outStrm->codec->rc_buffer_size = inStrm->codec->rc_buffer_size;
const size_t extra_size_alloc = (inStrm->codec->extradata_size > 0) ?
(inStrm->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE) :
0;
if (extra_size_alloc) {
outStrm->codec->extradata = (uint8_t*)av_mallocz(extra_size_alloc);
memcpy( outStrm->codec->extradata, inStrm->codec->extradata, inStrm->codec->extradata_size);
}
outStrm->codec->extradata_size = inStrm->codec->extradata_size;
AVRational input_time_base = inStrm->time_base;
AVRational frameRate = {25, 1};
if (inStrm->r_frame_rate.num && inStrm->r_frame_rate.den
&& (1.0 * inStrm->r_frame_rate.num / inStrm->r_frame_rate.den < 1000.0)) {
frameRate.num = inStrm->r_frame_rate.num;
frameRate.den = inStrm->r_frame_rate.den;
}
outStrm->r_frame_rate = frameRate;
outStrm->codec->time_base = inStrm->codec->time_base;
outStrm->codec->pix_fmt = inStrm->codec->pix_fmt;
outStrm->codec->width = width;
outStrm->codec->height = height;
outStrm->codec->has_b_frames = inStrm->codec->has_b_frames;
if (!outStrm->codec->sample_aspect_ratio.num) {
AVRational r0 = {0, 1};
outStrm->codec->sample_aspect_ratio =
outStrm->sample_aspect_ratio =
inStrm->sample_aspect_ratio.num ? inStrm->sample_aspect_ratio :
inStrm->codec->sample_aspect_ratio.num ?
inStrm->codec->sample_aspect_ratio : r0;
}
avformat_write_header(outCtx, NULL);
filterGraph = avfilter_graph_alloc();
if (!filterGraph) {
printf("could not open filter graph");
return -1;
}
AVFilter *crop = avfilter_get_by_name("crop");
AVFilter *buffer = avfilter_get_by_name("buffer");
AVFilter *buffersink = avfilter_get_by_name("buffersink");
char args[512];
snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
width, height, inStrm->codec->pix_fmt,
inStrm->codec->time_base.num, inStrm->codec->time_base.den,
inStrm->codec->sample_aspect_ratio.num, inStrm->codec->sample_aspect_ratio.den);
err = avfilter_graph_create_filter(&buffer_ctx, buffer, NULL, args, NULL, filterGraph);
if (err < 0) {
printf("error initializing buffer filter\n");
return err;
}
err = avfilter_graph_create_filter(&buffersink_ctx, buffersink, NULL, NULL, NULL, filterGraph);
if (err < 0) {
printf("unable to create buffersink filter\n");
return err;
}
snprintf(args, sizeof(args), "%d:%d", width, height);
err = avfilter_graph_create_filter(&crop_ctx, crop, NULL, args, NULL, filterGraph);
if (err < 0) {
printf("error initializing crop filter\n");
return err;
}
err = avfilter_link(buffer_ctx, 0, crop_ctx, 0);
if (err < 0) {
printf("error linking filters\n");
return err;
}
err = avfilter_link(crop_ctx, 0, buffersink_ctx, 0);
if (err < 0) {
printf("error linking filters\n");
return err;
}
err = avfilter_graph_config(filterGraph, NULL);
if (err < 0) {
printf("error configuring the filter graph\n");
return err;
}
printf("filtergraph configured\n");
for (;;) {
AVPacket packet = {0};
av_init_packet(&packet);
err = AVERROR(EAGAIN);
while (AVERROR(EAGAIN) == err)
err = av_read_frame(inCtx, &packet);
if (err < 0) {
if (AVERROR_EOF != err && AVERROR(EIO) != err) {
printf("eof error\n");
return 1;
} else {
break;
}
}
if (packet.stream_index == vs) {
//
// AVPacket pkt_temp_;
// memset(&pkt_temp_, 0, sizeof(pkt_temp_));
// AVPacket *pkt_temp = &pkt_temp_;
//
// *pkt_temp = packet;
//
// int error, got_frame;
// int new_packet = 1;
//
// error = avcodec_decode_video2(inStrm->codec, frame, &got_frame, pkt_temp);
// if(error < 0) {
// LOGE("error %d", error);
// }
//
// // if (error >= 0) {
//
// // push the video data from decoded frame into the filtergraph
// int err = av_buffersrc_write_frame(buffer_ctx, frame);
// if (err < 0) {
// LOGE("error writing frame to buffersrc");
// return -1;
// }
// // pull filtered video from the filtergraph
// for (;;) {
// int err = av_buffersink_get_frame(buffersink_ctx, oframe);
// if (err == AVERROR_EOF || err == AVERROR(EAGAIN))
// break;
// if (err < 0) {
// LOGE("error reading buffer from buffersink");
// return -1;
// }
// }
//
// LOGI("output frame");
err = av_interleaved_write_frame(outCtx, &packet);
if (err < 0) {
printf("error at write frame");
return -1;
}
//}
}
av_free_packet(&packet);
}
av_write_trailer(outCtx);
if (!(outCtx->oformat->flags & AVFMT_NOFILE) && outCtx->pb)
avio_close(outCtx->pb);
avformat_free_context(outCtx);
avformat_close_input(&inCtx);
return 0;
}
It looks like you are looking for vf_crop.
The CropContext contains a x, y, w, and h, which should be what you need to crop a video to a specific width and height.

Resources