%% %% This is file `cvss.ins', %% generated with the docstrip utility. %% %% The original source files were: %% %% cvss.dtx (with options: `install') %% ---------------------------------------------------------------- %% cvss --- A package to compute and display CVSS base scores %% E-mail: pierre@vivegnis.be %% Released under the LaTeX Project Public License v1.3c or later %% See http://www.latex-project.org/lppl.txt %% ---------------------------------------------------------------- %% \input docstrip.tex \keepsilent \askforoverwritefalse \preamble ---------------------------------------------------------------- cvss --- A package to compute and display CVSS base scores E-mail: pierre@vivegnis.be Released under the LaTeX Project Public License v1.3c or later See http://www.latex-project.org/lppl.txt ---------------------------------------------------------------- \endpreamble \postamble Copyright (C) 2022 by Pierre VIVEGNIS This work may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of this license or (at your option) any later version. The latest version of this license is in the file: http://www.latex-project.org/lppl.txt This work is "maintained" (as per LPPL maintenance status) by Pierre VIVEGNIS. This work consists of the file cvss.dtx and the derived files cvss.ins, cvss.pdf and cvss.sty. \endpostamble \usedir{tex/latex/cvss} \generate{ \file{\jobname.sty}{\from{\jobname.dtx}{package}} } \endbatchfile % \begin{syntax} % \cs{cvssScore} \Arg{CVSS string} % \end{syntax} % \begin{syntax} % \cs{cvssScorepretty} \Arg{CVSS string} % \end{syntax} % This macro will print a \textbf{colored} base CVSS 3.1 score of an \marg{input vector} (without \texttt{CVSS3.1/}). The output of this macro is a floating point CVSS score. % \end{function} % \begin{syntax} % \cs{cvssLevel} \Arg{CVSS string} % \end{syntax} % \begin{syntax} % \cs{cvssLevelpretty} \Arg{CVSS string} % \end{syntax} % \begin{syntax} % \cs{cvssTag} \Arg{CVSS string} % \end{syntax} % \begin{syntax} % \cs{cvssPrint} \Arg{CVSS string} % \end{syntax} % This macro will print all details of a CVSS string: colored level, score, and hyperlink to FIRST calculator, from an \marg{input vector} (without \texttt{CVSS3.1/}). % \end{function} % \begin{syntax} % \cs{category} \Arg{CVSS score} % \end{syntax} % \begin{syntax} % \cs{cvssFrame} \Arg{CVSS score} % \end{syntax} % This macro will output a CVSS tag based on a CVSS \textbf{level} passed as argument. The mandatory argument must be one of the defined CVSS levels (None, Info, Low, Medium, High or Critical), for example \texttt{Info}. % \end{function} % \begin{verbatim} % \end{verbatim} %\end{minipage}% %\end{minipage} % \begin{verbatim} % \end{verbatim} %\end{minipage}% %\end{minipage} % \begin{verbatim} % \end{verbatim} %\end{minipage}% %\end{minipage} % \begin{verbatim} % \end{verbatim} %\end{minipage}% %\end{minipage} % \begin{verbatim} %\cvssFrame{Low} % \end{verbatim} %\end{minipage}% %\cvssFrame{Low} %\category{9.9} %\category{9.9} \RequirePackage{expl3} \RequirePackage[skins]{tcolorbox} \tcbuselibrary{xparse} \RequirePackage{xstring} \RequirePackage{hyperref} \def\scoreLow{0.1} \def\scoreMed{4.0} \def\scoreHigh{7.0} \def\scoreCrit{9.0} \definecolor{color@cvss@None}{RGB}{83, 170, 51} \definecolor{color@cvss@Low}{RGB}{255, 203, 13} \definecolor{color@cvss@Medium}{RGB}{249, 160, 9} \definecolor{color@cvss@High}{RGB}{223, 61, 3} \definecolor{color@cvss@Critical}{RGB}{204, 5, 0} \ExplSyntaxOn \cs_new:Npn \__CVSS_roundup:n #1 { \fp_eval:n { ceil(#1,1) } \fp_compare:nT { ceil(#1,1)=ceil(#1,0) } {.0} } \msg_new:nnn { CVSS } { invalid-option }{ Value~'#2'~invalid~for~#1~#3.} \msg_new:nnn { CVSS } { invalid-structure } { CVSS~metric~#1~is~not~correct~(#2)~#3.} \msg_new:nnn { CVSS } { invalid-length } { CVSS~vector~"#1"~is~badly~formatted~#2.} \cs_new:Npn \__CVSS_parseAV:n #1 { \str_case_e:nnF {#1} { { N } { 0.85 } % Network { A } { 0.62 } % Adjacent { L } { 0.55 } % Local { P } { 0.2 } % Physical } { \msg_error:nnxxx { CVSS } { invalid-option } { parseAV } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parseAC:n #1 { \str_case_e:nnF {#1} { { H } { 0.44 } % High { L } { 0.77 } % Low } { \msg_error:nnxxx { CVSS } { invalid-option } { parseAC } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parsePRScopeUnchanged:n #1 { \str_case_e:nnF {#1} { { N } { 0.85 } % None { L } { 0.62 } % Low { H } { 0.27 } % High } { \msg_error:nnxxx { CVSS } { invalid-option } { parsePRScopeUnchanged } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parsePRScopeChanged:n #1 { \str_case_e:nnF {#1} { { N } { 0.85 } % None { L } { 0.68 } % Low { H } { 0.50 } % High } { \msg_error:nnxxx { CVSS } { invalid-option } { parsePRScopeChanged } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parsePR:nn #1#2 { % #1 Privilege Required % #2 Scope \str_case_e:nnF {#2} { { U } { \exp_args:Ne \__CVSS_parsePRScopeUnchanged:n {#1} } { C } { \exp_args:Ne \__CVSS_parsePRScopeChanged:n {#1} } } { \msg_error:nnxxx { CVSS } { invalid-option } { parsePR } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parseUI:n #1 { \str_case_e:nnF {#1} { { N } { 0.85 } % None { R } { 0.62 } % Required } { \msg_error:nnxxx { CVSS } { invalid-option } { parseUI } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parseCIA:n #1 { \str_case_e:nnF {#1} { { H } { 0.56 } { L } { 0.22 } { N } { 0.00 } } { \msg_error:nnxxx { CVSS } { invalid-option } { parseCIA } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_calcISS:nnn #1#2#3 { % #1 Confidentiality Impact %High H, Low L, None N % #2 Integrity Impact %High H, Low L, None N % #3 Availability Impact %High H, Low L, None N 1 - ( (1 - (\__CVSS_parseCIA:n {#1})) * (1 - (\__CVSS_parseCIA:n {#2})) * (1 - (\__CVSS_parseCIA:n {#3})) ) } \cs_new:Npn \__CVSS_calcImpact:nn #1#2 { % #1 = Scope % #2 = ISS % Scope Unchanged 6.42 × ISS % Scope Changed 7.52 × [ISS-0.029] - 3.25 × [ISS-0.02]15 \str_case_e:nnF {#1} { { U } { \fp_eval:n { 6.42 * (#2) } } % Scope UNCHANGED { C } { \fp_eval:n { 7.52 * ( (#2) - 0.029 ) - 3.25 * ( (#2) - 0.02 )^15 } } % Scope CHANGED } { \msg_error:nnxxx { CVSS } { invalid-option } { calcISC } {#1} {\msg_line_context:} } }% \cs_new:Npn \__CVSS_calcExploitability:nnnnn #1#2#3#4#5 { % #1 Attack Vector % #2 Attack Complexity % #3 Privileges Required % #4 User Interaction % #5 Scope % 8.22 × AttackVector × AttackComplexity × PrivilegeRequired × UserInteraction 8.22 * (\__CVSS_parseAV:n {#1}) * (\__CVSS_parseAC:n {#2}) * (\__CVSS_parsePR:nn {#3}{#5}) * (\__CVSS_parseUI:n {#4})% } \cs_new:Npn \__CVSS_cvssBaseScore:nnnnnnnn #1#2#3#4#5#6#7#8 { % #1 Attack Vector %Network N, Adjacent A, Local L, Physical P % #2 Attack Complexity %Low L, High H % #3 Privileges Required %None N, Low L, High H % #4 User Interaction %None N, Required R % #5 Scope %Unchanged U, Changed C % #6 Confidentiality Impact %High H, Low L, None N % #7 Integrity Impact %High H, Low L, None N % #8 Availability Impact %High H, Low L, None N % \fp_compare:nTF { \exp_args:Ne \__CVSS_calcImpact:nn {#5}{\exp_args:Ne \__CVSS_calcISS:nnn {#6}{#7}{#8}} <= 0 } % IF ISC <=0 { % ISC <=0 0.0 }{ % ISC > 0 \str_case_e:nnF {#5} { { U } { % SCOPE UNCHANGED \fp_eval:n { \__CVSS_roundup:n { min( ((\__CVSS_calcImpact:nn {#5}{\__CVSS_calcISS:nnn {#6}{#7}{#8}}) + (\__CVSS_calcExploitability:nnnnn {#1}{#2}{#3}{#4}{#5})), 10) } }% } { C } { % SCOPE CHANGED \fp_eval:n { \__CVSS_roundup:n { min( (1.08 * ((\__CVSS_calcImpact:nn {#5}{\__CVSS_calcISS:nnn {#6}{#7}{#8}}) + (\__CVSS_calcExploitability:nnnnn {#1}{#2}{#3}{#4}{#5}))), 10) } }% } } { \msg_error:nnxxx { CVSS } { invalid-option } { parseScope } {#1} {\msg_line_context:} } }% } \NewExpandableDocumentCommand \cvssScore { m }{% % Check that there are 35 chars \int_compare:nNnTF { \str_count_ignore_spaces:n {#1} } = {35}{}{ \msg_error:nnxx{CVSS}{invalid-length}{#1}{\msg_line_context:} } % Check AV value \str_if_eq:eeTF {\str_range:nnn {#1} {1} {3}} {AV:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{AV}{\str_range:nnn {#1} {1} {3}}{\msg_line_context:} } % Check AC value \str_if_eq:eeTF {\str_range:nnn {#1} {5} {8}} {/AC:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{AC}{\str_range:nnn {#1} {5} {8}}{\msg_line_context:} } % Check PR value \str_if_eq:eeTF {\str_range:nnn {#1} {10} {13}} {/PR:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{PR}{\str_range:nnn {#1} {10} {13}}{\msg_line_context:} } % Check UI value \str_if_eq:eeTF {\str_range:nnn {#1} {15} {18}} {/UI:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{UI}{\str_range:nnn {#1} {15} {18}}{\msg_line_context:} } % Check S value \str_if_eq:eeTF {\str_range:nnn {#1} {20} {22}} {/S:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{S}{\str_range:nnn {#1} {20} {22}}{\msg_line_context:} } % Check I value \str_if_eq:eeTF {\str_range:nnn {#1} {24} {26}} {/C:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{C}{\str_range:nnn {#1} {24} {26}}{\msg_line_context:} } % Check I value \str_if_eq:eeTF {\str_range:nnn {#1} {28} {30}} {/I:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{I}{\str_range:nnn {#1} {28} {30}}{\msg_line_context:} } % Check A value \str_if_eq:eeTF {\str_range:nnn {#1} {32} {34}} {/A:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{A}{\str_range:nnn {#1} {32} {34}}{\msg_line_context:} } \exp_args:Ne \__CVSS_cvssBaseScore:nnnnnnnn { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 4 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 9 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 14 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 19 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 23 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 27 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 31 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 35 } } }% \ExplSyntaxOff \ExplSyntaxOn \NewExpandableDocumentCommand \category { m }{% \fp_compare:nNnTF {#1}<{\scoreLow}{None} { \fp_compare:nNnTF{#1}<{\scoreMed}{Low} { \fp_compare:nNnTF{#1}<{\scoreHigh}{Medium} { \fp_compare:nNnTF{#1}<{\scoreCrit}{High} {Critical} }% }% }% }% \ExplSyntaxOff \newcommand{\cvssScorepretty}[1]{% \def\CVSScategory{\category{\cvssScore{#1}}}% \textcolor{color@cvss@\CVSScategory}{\cvssScore{#1}}% }% \newcommand{\cvssLevel}[1]{% \def\CVSSscore{\cvssScore{#1}}% \category{\CVSSscore}% }% \newcommand{\cvssLevelpretty}[1]{% \def\CVSScategory{\category{\cvssScore{#1}}}% \textcolor{color@cvss@\CVSScategory}{\CVSScategory}% }% \DeclareTotalTCBox{\cvssFrame}{m}{ enhanced,nobeforeafter, tcbox raise base, boxrule=0.4pt, top=0mm,bottom=0mm,right=1mm,left=1mm, arc=1pt, boxsep=2pt, colframe=color@cvss@#1, colback=tcbcolframe, coltext=black, }{#1}% \MakeRobust\cvssFrame \newcommand{\cvssTag}[1]{% \def\CVSSscore{\cvssScore{#1}}% \cvssFrame{\category{\CVSSscore}}% }% \newcommand{\cvssPrint}[1]{% \def\CVSSscore{\cvssScore{#1}} \cvssFrame{\category{\CVSSscore}} \quad \CVSSscore \quad% \href{https://www.first.org/cvss/calculator/3.1\#CVSS:3.1/#1}{CVSS:3.1/#1} }% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% Copyright (C) 2022 by Pierre VIVEGNIS %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License (LPPL), either %% version 1.3c of this license or (at your option) any later %% version. The latest version of this license is in the file: %% %% http://www.latex-project.org/lppl.txt %% %% This work is "maintained" (as per LPPL maintenance status) by %% Pierre VIVEGNIS. %% %% This work consists of the file cvss.dtx %% and the derived files cvss.ins, %% cvss.pdf and %% cvss.sty. %% %% %% End of file `cvss.ins'.