diff options
Diffstat (limited to 'libs/libssh2/src/pem.c')
-rw-r--r-- | libs/libssh2/src/pem.c | 112 |
1 files changed, 66 insertions, 46 deletions
diff --git a/libs/libssh2/src/pem.c b/libs/libssh2/src/pem.c index c658896809..c9ab774690 100644 --- a/libs/libssh2/src/pem.c +++ b/libs/libssh2/src/pem.c @@ -126,8 +126,7 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, if(readline(line, LINE_SIZE, fp)) { return -1; } - } - while(strcmp(line, headerbegin) != 0); + } while(strcmp(line, headerbegin) != 0); if(readline(line, LINE_SIZE, fp)) { return -1; @@ -263,13 +262,8 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, goto out; } - while(len_decrypted <= (int)*datalen - blocksize) { - if(method->crypt(session, *data + len_decrypted, blocksize, - &abstract, - len_decrypted == 0 ? FIRST_BLOCK : - ((len_decrypted == (int)*datalen - blocksize) ? - LAST_BLOCK : MIDDLE_BLOCK) - )) { + if(method->flags & LIBSSH2_CRYPT_FLAG_REQUIRES_FULL_PACKET) { + if(method->crypt(session, 0, *data, *datalen, &abstract, 0)) { ret = LIBSSH2_ERROR_DECRYPT; _libssh2_explicit_zero((char *)secret, sizeof(secret)); method->dtor(session, &abstract); @@ -277,8 +271,25 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session, LIBSSH2_FREE(session, *data); goto out; } + } + else { + while(len_decrypted <= (int)*datalen - blocksize) { + if(method->crypt(session, 0, *data + len_decrypted, blocksize, + &abstract, + len_decrypted == 0 ? FIRST_BLOCK : + ((len_decrypted == (int)*datalen - blocksize) ? + LAST_BLOCK : MIDDLE_BLOCK) + )) { + ret = LIBSSH2_ERROR_DECRYPT; + _libssh2_explicit_zero((char *)secret, sizeof(secret)); + method->dtor(session, &abstract); + _libssh2_explicit_zero(*data, *datalen); + LIBSSH2_FREE(session, *data); + goto out; + } - len_decrypted += blocksize; + len_decrypted += blocksize; + } } /* Account for padding */ @@ -323,8 +334,7 @@ _libssh2_pem_parse_memory(LIBSSH2_SESSION * session, if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) { return -1; } - } - while(strcmp(line, headerbegin) != 0); + } while(strcmp(line, headerbegin) != 0); *line = '\0'; @@ -599,46 +609,58 @@ _libssh2_openssh_pem_parse_data(LIBSSH2_SESSION * session, goto out; } - while((size_t)len_decrypted <= decrypted.len - blocksize) { - /* We always pass MIDDLE_BLOCK here because OpenSSH Key Files - * do not use AAD to authenticate the length. - * Furthermore, the authentication tag is appended after the - * encrypted key, and the length of the authentication tag is - * not included in the key length, so we check it after the - * loop. - */ - if(method->crypt(session, decrypted.data + len_decrypted, - blocksize, + if(method->flags & LIBSSH2_CRYPT_FLAG_REQUIRES_FULL_PACKET) { + if(method->crypt(session, 0, decrypted.data, + decrypted.len, &abstract, MIDDLE_BLOCK)) { ret = LIBSSH2_ERROR_DECRYPT; method->dtor(session, &abstract); goto out; } - - len_decrypted += blocksize; } + else { + while((size_t)len_decrypted <= decrypted.len - blocksize) { + /* We always pass MIDDLE_BLOCK here because OpenSSH Key Files + * do not use AAD to authenticate the length. + * Furthermore, the authentication tag is appended after the + * encrypted key, and the length of the authentication tag is + * not included in the key length, so we check it after the + * loop. + */ + if(method->crypt(session, 0, decrypted.data + len_decrypted, + blocksize, + &abstract, + MIDDLE_BLOCK)) { + ret = LIBSSH2_ERROR_DECRYPT; + method->dtor(session, &abstract); + goto out; + } - /* No padding */ - - /* for the AES GCM methods, the 16 byte authentication tag is - * appended to the encrypted key */ - if(strcmp(method->name, "aes256-gcm@openssh.com") == 0 || - strcmp(method->name, "aes128-gcm@openssh.com") == 0) { - if(!_libssh2_check_length(&decoded, 16)) { - ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, - "GCM auth tag missing"); - method->dtor(session, &abstract); - goto out; + len_decrypted += blocksize; } - if(method->crypt(session, decoded.dataptr, 16, &abstract, - LAST_BLOCK)) { - ret = _libssh2_error(session, LIBSSH2_ERROR_DECRYPT, - "GCM auth tag invalid"); - method->dtor(session, &abstract); - goto out; + + /* No padding */ + + /* for the AES GCM methods, the 16 byte authentication tag is + * appended to the encrypted key */ + if(strcmp(method->name, "aes256-gcm@openssh.com") == 0 || + strcmp(method->name, "aes128-gcm@openssh.com") == 0) { + if(!_libssh2_check_length(&decoded, 16)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "GCM auth tag missing"); + method->dtor(session, &abstract); + goto out; + } + if(method->crypt(session, 0, decoded.dataptr, 16, &abstract, + LAST_BLOCK)) { + ret = _libssh2_error(session, LIBSSH2_ERROR_DECRYPT, + "GCM auth tag invalid"); + method->dtor(session, &abstract); + goto out; + } + decoded.dataptr += 16; } - decoded.dataptr += 16; } method->dtor(session, &abstract); @@ -722,8 +744,7 @@ _libssh2_openssh_pem_parse(LIBSSH2_SESSION * session, if(readline(line, LINE_SIZE, fp)) { return -1; } - } - while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0); + } while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0); if(readline(line, LINE_SIZE, fp)) { return -1; @@ -803,8 +824,7 @@ _libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session, if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) { return -1; } - } - while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0); + } while(strcmp(line, OPENSSH_HEADER_BEGIN) != 0); *line = '\0'; |